//
//  APIError.swift
//  Casecord
//
//  Created by baozi on 2024/1/3.
//

import Foundation
struct APIError: Swift.Error, Equatable, CustomStringConvertible {
    var code: Int?
    var message: String?
    var data: Any?
    
    /// moya error
    static var moyaError = APIError(code: -1000)
    
    static var serverError = APIError(code: -999)
    /// 连接错误。有可能是没网
    static var connectionError = APIError(code: -998)
    /// 不可用的response数据
    static var jsonDataError = APIError(code: -997)
    /// 超时错误
    static var timeout = APIError(code: -996)
    /// 您的账号在另一个设备上登录了,需要重新登录
    static var err_login_kickout_1000101 = APIError(code: 1000101)
    /// 账号已被禁用
    static var err_account_disable_1000102 = APIError(code: 1000102)
    /// 账号已被注销
    static var err_account_cancel_1000103 = APIError(code: 1000103)
    /// 时间戳异常，需要校正本地事件
    static var err_timeoffset_1000006 = APIError(code: 1000006)
    /// 内购订单重复验签
    static var err_iap_repeat_1000022 = APIError(code: 1000022)
    /// 通话中余额不足124(历史代码中抛出)
    static var err_no_token_1000124 = APIError(code: 1000124)
    /// 余额不足
    static var err_no_token_1000156 = APIError(code: 1000156)
    
    static func == (lhs: Self, rhs: Self) -> Bool {
        return lhs.code == rhs.code
    }
    
    init(code: Int?, message: String? = nil, data: Any? = nil) {
        self.code = code
        self.message = message
        self.data = data
    }
    
    init?(_ res: APIResult) {
        if res.code == 200 {
            return nil
        }
        let code = res.errorCode ?? res.code
        guard let code = code else {
            return nil
        }
        switch code {
        case APIError.err_login_kickout_1000101.code:
            self = APIError.err_login_kickout_1000101
        case APIError.err_account_disable_1000102.code:
            self = APIError.err_account_disable_1000102
        case APIError.err_account_cancel_1000103.code:
            self = APIError.err_account_cancel_1000103
        case APIError.err_timeoffset_1000006.code:
            self = APIError(code: code, message: res.errorMsg, data: res.timestamp)
        default:
            self = APIError(code: code, message: res.errorMsg)
        }
    }
    
    mutating func message(_ msg: String?) -> Self {
        self.message = msg
        return self
    }
    
    func copy() -> APIError {
        let cp = self
        return cp
    }
    
    var isNoTokenError: Bool {
        self == APIError.err_no_token_1000156 || self == APIError.err_no_token_1000124
    }
    
    var description: String {
        self.message ?? "Operation Error"
    }
    
    public var localizedDescription: String {
        self.message ?? "Operation Error"
    }
}

extension Error {
    var errorMessage: String {
        if let _error = self as? APIError {
            return _error.localizedDescription
        } else {
            return self.localizedDescription
        }
    }
}

// MARK: 增加重试选项
/// 可重试的错误
protocol RetryTestable {
    /// 在调用层声明操作出错时需要重试时，
    /// 判断特定错误是否可以重试
    var shouldRetry: Bool { get }
}

extension RetryTestable {
    var shouldRetry: Bool { false }
}
extension APIError {
    
    typealias RetryTestClosure = (Error) -> Bool
    static func retryTest(and customTest: RetryTestClosure? = nil) -> RetryTestClosure {
        { (error) -> Bool in
            if let customTest = customTest, customTest(error) {
                return true
            }
            if let apiError = error as? RetryTestable, apiError.shouldRetry {
                return true
            }
            return false
        }
    }
}
